package com.yonyou.crm.base.measure.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.yonyou.crm.base.measure.entity.MeasuresVO;
import com.yonyou.crm.common.biz.service.BaseBizServiceImpl;
import com.yonyou.crm.common.enumeration.entity.EnableStateEnum;
import com.yonyou.crm.common.enumeration.service.EnumBizServiceImpl;
import com.yonyou.crm.common.exception.CrmBusinessException;
import com.yonyou.crm.common.field.handler.FieldRelationHandler;
import com.yonyou.crm.common.field.relation.EnumFieldRelation;
import com.yonyou.crm.common.field.relation.FieldRelation;
import com.yonyou.crm.common.page.entity.Page;
import com.yonyou.iuap.context.InvocationInfoProxy;

@Service
public class MeasuresBizServiceImpl extends BaseBizServiceImpl<MeasuresVO> {
	
	@Autowired
	private EnumBizServiceImpl enumService;
	
	public Page<MeasuresVO> getList(Page<MeasuresVO> page,Map<String, Object> paramMap) {
		
		Page<MeasuresVO> measurePage = null;
		if (paramMap != null) {
			measurePage = super.pageSelect(MeasuresVO.class, page, paramMap.keySet().toArray(new String[0]), paramMap.values().toArray(new Object[0]));
		}
		else {
			measurePage = super.pageSelect(MeasuresVO.class, page, null, null);
		}
		
		trans(measurePage.getData());
		
		return measurePage;
	}
	
	public MeasuresVO getDetail(Long id) {
		MeasuresVO newMeasure = super.getVOById(MeasuresVO.class, id);
		trans(Arrays.asList(newMeasure));
		return newMeasure;
	}
	
	@Override
	protected void beforeSaveVO(MeasuresVO vo) {
		
		super.beforeSaveVO(vo);
		
		int codeCount = getMeasureCountByCode(vo.getCode(), null);
		if (codeCount > 0) {
			throw new CrmBusinessException("代号已存在");
		}
		
		int nameCount = getMeasureCountByName(vo.getName(), null);
		if (nameCount > 0) {
			throw new CrmBusinessException("名称已存在");
		}
		
		Long loginUserID =  new Long(InvocationInfoProxy.getParameter("id"));
		Date date = new Date();
				
		vo.setCreatedTime(date);
		vo.setCreatedUserId(loginUserID);
		
		vo.setEnableState(EnableStateEnum.ENABLE.getValue());
	}
	
	@Override
	protected void afterSaveVO(MeasuresVO vo) {
		super.afterSaveVO(vo);
		trans(Arrays.asList(vo));
	}
	
	@Override
	protected void beforeUpdateVO(MeasuresVO vo) {
		
		super.beforeUpdateVO(vo);
		
		vo.setModifiedTime(new Date());
		vo.setModifiedUserId(new Long(InvocationInfoProxy.getParameter("id")));
	}
	
	@Override
	protected void afterUpdateVO(MeasuresVO vo) {
		super.afterUpdateVO(vo);
		trans(Arrays.asList(vo));
	}
	
	public MeasuresVO update(MeasuresVO measure) {
		
		int codeCount = getMeasureCountByCode(measure.getCode(), measure.getId());
		if (codeCount > 0) {
			throw new CrmBusinessException("代码已存在");
		}
		
		int nameCount = getMeasureCountByName(measure.getName(), measure.getId());
		if (nameCount > 0) {
			throw new CrmBusinessException("名称已存在");
		}
		
		//校验计量单位是否被引用
		if (checkRefStatus(measure.getId())) {
			throw new CrmBusinessException("计量单位已被引用，禁止修改！");
		}
		
		return super.updateVO(measure);
	}

	@Override
	protected void beforeDeleteVO(MeasuresVO vo) {
		
		super.beforeDeleteVO(vo);
		
		//校验计量单位是否被引用
		boolean refFlag = checkRefStatus(vo.getId());
		if (refFlag) {
			throw new CrmBusinessException("计量单位已被引用，禁止删除！");
		}
				
		vo.setDeletedTime(new Date());
		vo.setDeletedUserId(new Long(InvocationInfoProxy.getParameter("id")));
	}
	
	public int delete(Long id) {
		MeasuresVO measure = new MeasuresVO();
		measure.setId(id);
		return super.deleteVO(measure);
	}
	
	public String batchDelete(String[] ids) {
		
		if (ids == null || ids.length == 0) {
			return "";
		}

		Set<String> idSet = new HashSet<String>();
		for (String id : ids) {
			idSet.add(id);
		}
		
		int totalCount = idSet.size();
		
		StringBuffer reasonBuffer = new StringBuffer("【");

		//是否被产品引用
		List<Map<String, Object>> prdtypeList = getProductByPrdType(idSet.toArray(new String[0]));
		
		if (prdtypeList != null && prdtypeList.size() > 0) {
			
			for (Map<String, Object> map : prdtypeList) {
				
				reasonBuffer.append(map.get("name"));
				reasonBuffer.append(",");

				String typeId = map.get("id").toString();
				//被产品引用品牌不能删除
				idSet.remove(typeId);
			}
			reasonBuffer.delete(reasonBuffer.length()-1, reasonBuffer.length());
			reasonBuffer.append("】已被产品引用，当前计量单位不可删除！");
		}
		
		int successCount = idSet.size();
		int failCount = totalCount - idSet.size();
		String message = failCount == 0 ? "成功" + successCount + "条。" : "成功" + successCount + "条，失败" + failCount + "条。\n失败原因：" + reasonBuffer.toString();
		
		if (successCount > 0) {
			super.batchDeleteByIDs(MeasuresVO.class, idSet);
		}
		
		return message;
	}
	
	public MeasuresVO updateEnableState(Long id, Integer enableState) {
		
		MeasuresVO measure = new MeasuresVO();
		measure.setId(id);
		measure.setEnableState(enableState);
		measure.setEnableTime(new Date());
		measure.setEnableUserId(new Long(InvocationInfoProxy.getParameter("id")));
		return super.updateVO(measure);
	}
	
	public void batchUpdateEnableState(String[] ids, Integer enableState) {
		
		Map<String, Object> enableParaMap = new HashMap<String, Object>();
		enableParaMap.put("ids", ids);
		enableParaMap.put("enableState", enableState);
		
		Long loginUserID =  new Long(InvocationInfoProxy.getParameter("id"));
		Date date = new Date();
		enableParaMap.put("enableTime", date);
		enableParaMap.put("enableUserId", loginUserID);
				
		dao.updateSql(MeasuresVO.class, "batchUpdateEnableState", enableParaMap);

	}
	
	public int getMeasureCountByCode(String code, Long id) {
		
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("code", code);
		paraMap.put("id", id);
		return dao.countAll(MeasuresVO.class, "getMeasureCountByCode", paraMap);
	}
	
	public int getMeasureCountByName(String name, Long id) {
		
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("name", name);
		paraMap.put("id", id);
		return dao.countAll(MeasuresVO.class, "getMeasureCountByName", paraMap);
	}
	
	/**
	 * 计量单位名称翻译
	 * @param ids
	 * @return
	 */
	public Object selectFieldsByIds(Object[] ids) {
		Map<String, Object> para = new HashMap<String, Object>();
		para.put("ids", ids);
		return dao.selectList(MeasuresVO.class, "selectFieldsByIds", para);
	}
	
	public int getMeasureCountByIdFromProduct(Long id) {
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("id", id);
		return dao.countAll(MeasuresVO.class, "getMeasureCountByIdFromProduct", paraMap);
	}
	
	/**
	 * 校验计量单位是否被引用
	 * @param id
	 * @return boolean
	 */
	private boolean checkRefStatus(Long id) {
		boolean refFlag = false;
		if(getMeasureCountByIdFromProduct(id) > 0) {
			refFlag = true;
		}
		return refFlag;
	}

	/**
	 * 参照列表
	 * 参照字段：id、名称、英文名称、备注
	 * @param paraMap
	 * @return
	 */
	public List<MeasuresVO> getRefList(Map<String, Object> paraMap) {

		if (paraMap == null) {
			paraMap = new HashMap<String, Object>();
		}
		
		paraMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
		
		return dao.selectVoList(MeasuresVO.class, "getRefList", paraMap);
	}
	
	/**
	 * 分页参照列表
	 * 参照字段：id、名称、英文名称、备注
	 * @param page
	 * @param paraMap
	 * @return
	 */
	public Page<MeasuresVO> getRefPage(Page<MeasuresVO> page, Map<String, Object> paraMap) {

		if (paraMap == null) {
			paraMap = new HashMap<String, Object>();
		}
		
		paraMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
		
		return dao.pageSelect(MeasuresVO.class, page, "getRefPage", "countRefPage", paraMap);
	}
	
	/*
	 * 对枚举、参照转换
	 */
	private List<MeasuresVO> trans(List<MeasuresVO> voList) {
		
		if (voList != null && voList.size() > 0) {
			
			List<FieldRelation<MeasuresVO>> relations = new ArrayList<FieldRelation<MeasuresVO>>();
			relations.add(new EnumFieldRelation<MeasuresVO>(MeasuresVO.class, "enableState", "enableStateName", enumService, "enable_state"));
			
			new FieldRelationHandler<MeasuresVO>().handler(voList, relations);
		}

		return voList;
	}
	
	/**
	 * 校验计量单位是否被产品引用
	 * @param ids
	 * @return
	 */
	public List<Map<String, Object>> getProductByPrdType(String[] ids) {
		if (ids == null || ids.length == 0) {
			return null;
		}
		return dao.selectList(MeasuresVO.class, "getProductByPrdType", ids);
	}
}
